home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / falcon / bonus / gamefix / gamefix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-18  |  24.1 KB  |  786 lines

  1. /********************************************************************/
  2. /* Modulname      : GAMEFIX.C                                       */
  3. /* Autor          : Thomas Binder                                   */
  4. /* Zweck          : Verbesserung der Abwärtskompatibilität des      */
  5. /*                  Falcon030. Einstellprogramm mit GEM-Bedienung,  */
  6. /*                  das auch das Abspeichern kleiner Startpro-      */
  7. /*                  gramme ermöglicht.                              */
  8. /* Compiler       : Pure C 1.0                                      */
  9. /* Erstellt am    : 10.08.1993                                      */
  10. /* Letzte Änderung: 03.09.1993                                      */
  11. /********************************************************************/
  12.  
  13. #include <aes.h>
  14. #include <tos.h>
  15. #include <falcon.h>
  16. #include <portab.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <stddef.h>
  20. #include <string.h>
  21. #include "gamefix.rsh"
  22. #include "gamefix.h"
  23. #include "mini1.hex"
  24. #include "mini2.hex"
  25.  
  26. /* Prototypen */
  27. LONG reset(void);
  28. LONG get_settings(void);
  29. LONG set(void);
  30. WORD do_dialog(OBJECT *tree, WORD sobj,
  31.     WORD (*action)(OBJECT *tree, WORD obj));
  32. WORD handle_savedial(OBJECT *tree, WORD obj);
  33. WORD handle_maindial(OBJECT *tree, WORD obj);
  34. void cross(OBJECT *tree, WORD obj);
  35. void set_atten(WORD redraw);
  36. void boot(void);
  37. void save(void);
  38. WORD do_save(char *rout, LONG size);
  39. WORD take_settings(void);
  40. void put_settings(void);
  41. WORD tree_walk(OBJECT *tree, WORD start,
  42. WORD (*action)(OBJECT *tree, WORD obj));
  43. WORD adapt_size(OBJECT *tree, WORD obj);
  44. WORD fileselect(char *path, char *name,
  45.     WORD *button, char *title);
  46. WORD exist(char *file);
  47. WORD get_cookie(ULONG cookie, ULONG *value);
  48. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  49.  
  50. /* Globale Variablen */
  51. ULONG   ram;
  52. WORD    magic_pack[1280],
  53.         rbuts[] = {RAM512K, RAM1MB,
  54.             RAM2MB, RAM4MB},
  55.         volume,
  56.         char_w, char_h;
  57. char    path[129];
  58.  
  59. WORD main(void)
  60. {
  61.     WORD    old_ltatten,
  62.             old_rtatten,
  63.             button,
  64.             end = 0,
  65.             i, j,
  66.             dummy;
  67.     ULONG   _mch = 0;
  68.     
  69.     if (appl_init() < 0)
  70.         return(0);
  71.     /* Resourcen skalieren */
  72.     rsrc_init();
  73.     /* Testen, ob Rechner ein F030 ist */
  74.     if ((!get_cookie('_MCH', &_mch)) || (_mch < 0x30000L))
  75.     {
  76.         form_alert(1, NOFALCON);
  77.         appl_exit();
  78.         return(0);
  79.     }
  80.     /* Testen, ob Multitasking-AES laufen */
  81.     if (_GemParBlk.global[1] != 1)
  82.     {
  83.         form_alert(1, STOSONLY);
  84.         appl_exit();
  85.         return(0);
  86.     }
  87.     graf_mouse(ARROW, NULL);
  88.     graf_handle(&char_w, &char_h, &dummy, &dummy);
  89.     /* Aktuellen Pfad holen */
  90.     sprintf(path, "%c:", (char)(Dgetdrv() + 65));
  91.     Dgetpath(&path[2], 0);
  92.     strcat(path, "\\*.PRG");
  93.     /* Ramgröße des F030 und aktuelle Einstellungen holen */
  94.     ram = (ULONG)Supexec(get_settings);
  95.     /* Feststellen, welche Ramgröße maximal genommen werden darf */
  96.     for (i = 3; (ram <= ramsizes[i]) && (i > 1); i--)
  97.     {
  98.         MAINDIAL[rbuts[i]].ob_state |= DISABLED;
  99.         MAINDIAL[rbuts[i] + 1].ob_state |= DISABLED;
  100.     }
  101.     /* Feststellen, welche Ramgröße mindestens genommen werden muß */
  102.     /* (wegen Magic Pack) */
  103.     for (j = 0; (ULONG)magic_pack >=
  104.         ramsizes[j]; j++)
  105.     {
  106.         MAINDIAL[rbuts[j]].ob_state |= DISABLED;
  107.         MAINDIAL[rbuts[j] + 1].ob_state |= DISABLED;
  108.     }
  109.     /* Abbruch, wenn Mindeswert > Maximalwert */
  110.     if (j > i)
  111.     {
  112.         form_alert(1, NORAM);
  113.         appl_exit();
  114.         return(0);
  115.     }
  116.     /* Aktuelle Einstellungen in Dialog eintragen */
  117.     MAINDIAL[rbuts[i]].ob_state |= SELECTED;
  118.     volume = 15 - (WORD)(MIN((old_ltatten =
  119.         (WORD)soundcmd(LTATTEN, -1)),
  120.         old_rtatten = (WORD)soundcmd(RTATTEN, -1)) / 16);
  121.     set_atten(0);
  122.     MAINDIAL[DCACHE].ob_state = (settings[_DATACACHE] *
  123.         CROSSED) | SELECTED;
  124.     MAINDIAL[ICACHE].ob_state = (settings[_INSTCACHE] *
  125.         CROSSED) | SELECTED;
  126.     MAINDIAL[CPU8MHZ].ob_state = (settings[_CPU8MHZ] *
  127.         CROSSED) | SELECTED;
  128.     MAINDIAL[BLIT8MHZ].ob_state = (settings[_BLIT8MHZ] *
  129.         CROSSED) | SELECTED;
  130.     MAINDIAL[STEBUS].ob_state = (settings[_BUSMODE] *
  131.         CROSSED) | SELECTED;
  132.     MAINDIAL[SPEAKER].ob_state = (settings[_SPEAKER] *
  133.         CROSSED) | SELECTED;
  134.     MAINDIAL[TIMERA].ob_state = (settings[_TIMERA] *
  135.         CROSSED) | SELECTED;
  136.     MAINDIAL[MFPI7].ob_state = (settings[_MFPI7] *
  137.         CROSSED) | SELECTED;
  138.     MAINDIAL[SCRADR].ob_state |= CROSSED;
  139.     do
  140.     {
  141.         /* Dialog bearbeiten */
  142.         if ((button = do_dialog(MAINDIAL,
  143.             0, handle_maindial)) != OK)
  144.         {
  145.             if (button == ABBRUCH)
  146.             {
  147.                 /* Lautstärke auf alten Wert zurücksetzen */
  148.                 soundcmd(LTATTEN, old_ltatten);
  149.                 soundcmd(RTATTEN, old_rtatten);
  150.                 end = 1;
  151.             }
  152.             else
  153.             {
  154.                 /* Das Feld settings entsprechend den Einstellungen */
  155.                 /* Dialog belegen */
  156.                 put_settings();
  157.                 /* Speicherroutine aufrufen */
  158.                 save();
  159.             }
  160.         }
  161.         else
  162.         {
  163.             /* settings-Feld belegen */
  164.             put_settings();
  165.             /* Booten oder Übernehmen? */
  166.             if (form_alert(1, BOOTEN) == 1)
  167.                 boot();
  168.             else
  169.                 end = take_settings();
  170.         }
  171.     } while (!end);
  172.     /* Programm abmelden und tschüß */
  173.     appl_exit();
  174.     return(0);
  175. }
  176.  
  177. /* Hier werden die Miniprogramme gespeichert */
  178. void save(void)
  179. {
  180.     WORD    cont,
  181.             i;
  182.     char    title[41], name[129];
  183.     
  184.     /* Welcher Miniprogrammtyp soll's denn sein? */
  185.     cont = do_dialog(SAVEDIAL, 0, handle_savedial);
  186.     if (cont != SAVEOK)
  187.         return;
  188.     if (SAVEDIAL[BOOTPRG].ob_state & SELECTED)
  189.     {
  190.         /* Warnung ausgeben, wenn 1 MB-Rechner mit 1 MB konfiguriert */
  191.         /* werden soll, weil dabei der PMMU-Baum nicht geschützt */
  192.         /* werden kann */
  193.         if ((ram <= 0x100000LU) &&
  194.             settings[_RAMCONFIG])
  195.         {
  196.             if (settings[_SCRBASE])
  197.                 cont = (do_dialog(WARNING1, 0, 0L) == W1OK);
  198.             else
  199.                 cont = (do_dialog(WARNING4, 0, 0L) == W4OK);
  200.             if (!cont)
  201.                 return;
  202.         }
  203.         /* Programmtyp "mini1" speichern */
  204.         if (do_save(mini1, sizeof(mini1)))
  205.             form_alert(1, DISKERR);
  206.     }
  207.     else
  208.     {
  209.         /* Warnung ausgeben, daß bei Programmen, die nicht booten */
  210.         /* sollen, die Ramkonfiguration unberücksichtigt bleibt */
  211.         /* und somit kein sicherer Platz für den PMMU-Baum da ist */
  212.         cont = (do_dialog(WARNING2, 0, 0L)
  213.             == W2OK);
  214.         if (!cont)
  215.             return;
  216.         /* Soll das Einstellprogramm ein Programm nachladen? */
  217.         if (form_alert(1, LOADONE) == 1)
  218.         {
  219.             /* Wenn ja, welches? */
  220.             sprintf(name, "");
  221.             sprintf(title, "Nachzuladendes Programm wählen!");
  222.             if (fileselect(path, name, &cont, title))
  223.             {
  224.                 if (!cont)
  225.                     return;
  226.                 for (i = 0; ((WORD *)mini2)[i]
  227.                     != (WORD)0xabce; i++);
  228.                 strcpy(&mini2[--i * 2], name);
  229.             }
  230.             else
  231.                 return;
  232.         }
  233.         /* Programmtyp "mini2" speichern */
  234.         if (do_save(mini2, sizeof(mini2)))
  235.             form_alert(1, DISKERR);
  236.     }
  237. }
  238.  
  239. /* Routine zum Schreiben eines Miniprogramms */
  240. WORD do_save(char *rout, LONG size)
  241. {
  242.     WORD    i, j,
  243.             handle,
  244.             save;
  245.     char    name[129], title[41];
  246.     
  247.     /* Werte aus settings-Feld in Programm eintragen */
  248.     for (i = 0; ((WORD *)rout)[i] != (WORD)0xabdc; i++);
  249.     for (j = 0; j < 11; j++)
  250.         ((WORD *)rout)[++i] = settings[j];
  251.     /* Gewünschten Namen erfragen */
  252.     sprintf(title, "Name des Miniprogramms wählen!");
  253.     sprintf(name, "");
  254.     if (fileselect(path, name, &save, title))
  255.         if (save)
  256.         {
  257.             /* Nachfragen, ob ein existierendes File überschrieben */
  258.             /* werden soll */
  259.             if (exist(name))
  260.             {
  261.                 if (form_alert(1, FEXISTS) == 2)
  262.                     return(0);
  263.             }
  264.             /* Datei anlegen und Routine hineinschreiben */
  265.             handle = (WORD)Fcreate(name, 0);
  266.             if (handle < 0)
  267.                 return(1);
  268.             Fwrite(handle, size, (void *)rout);
  269.             Fclose(handle);
  270.         }
  271.     return(0);
  272. }
  273.  
  274. /* Magic Pack anlegen und Reset auslösen */
  275. void boot(void)
  276. {
  277.     WORD    i, j,
  278.             sum,
  279.             first,
  280.             cont,
  281.             checkpos,
  282.             pos;
  283.     LONG    help;
  284.     
  285.     /* Warnung ausgeben, wenn 1 MB-Rechner mit 1 MB konfiguriert */
  286.     /* werden soll, weil dabei der PMMU-Baum nicht geschützt */
  287.     /* werden kann */
  288.     if ((ram <= 0x100000LU) &&
  289.         settings[_RAMCONFIG])
  290.     {
  291.         if (settings[_SCRBASE])
  292.             cont = (do_dialog(WARNING1, 0, 0L) == W1OK);
  293.         else
  294.             cont = (do_dialog(WARNING4, 0, 0L) == W4OK);
  295.          if (!cont)
  296.             return;
  297.     }
  298.     /* Warnung vor Reset */
  299.     if (form_alert(1, RESET) == 2)
  300.         return;
  301.     /* Startadresse der GEMDOS-Routine für die alte Bildschirmadresse */
  302.     /* und des PMMU-Baums bestimmen */
  303.     if (ramsizes[settings[_RAMCONFIG]] == ram)
  304.     {
  305.         gdrout = (WORD *)0x600L;
  306.         rootpointer[1] = 0x700L;
  307.         if (!Super((void *)1L))
  308.             Super(0L);
  309.     }
  310.     else
  311.     {
  312.         gdrout = (WORD *)(ram - 256LU);
  313.         rootpointer[1] = ram - 512LU;
  314.     }
  315.     /* PMMU-Baum kopieren */
  316.     for (i = 0; i < 64; i++)
  317.     {
  318.         if ((new_pmmu_tree[i] / 65536LU) ==
  319.             0xffffLU)
  320.         {
  321.             /* Bei entsprechend gekennzeichnetem Eintrag den richtigen */
  322.             /* Offset berechnen */
  323.             new_pmmu_tree[i] =
  324.                 rootpointer[1] +
  325.                 (new_pmmu_tree[i] & 65535LU);
  326.         }
  327.         else
  328.         {
  329.             /* Sollen Daten- und Befehlscache ausgeschaltet werden, im */
  330.             /* PMMU-Baum Cache-Inhibit-Flag setzen */
  331.             if (!settings[_DATACACHE] &&
  332.                 !settings[_INSTCACHE])
  333.             {
  334.                 new_pmmu_tree[i] |= 64LU;
  335.             }
  336.         }
  337.         ((LONG *)rootpointer[1])[i] =
  338.             new_pmmu_tree[i];
  339.     }
  340.     /* GEMDOS-Routine kopieren (egal, ob sie gebraucht wird, oder nicht */
  341.     for (i = 0; _gemdos[i] != (WORD)0xabcd; i++)
  342.         gdrout[i] = _gemdos[i];
  343.     gdrout += 6L;
  344.     /* Beginn des Magic Pack bestimmen (muß auf 512-Byte-Grenze fallen) */
  345.     /* Die Magic Packs sind übrigens offiziell nicht dokumentiert, sie */
  346.     /* sollten also nur sehr selten benutzt werden */
  347.     help = (LONG)magic_pack;
  348.     if (help % 512L)
  349.         help += 512L - (help % 512L);
  350.     first = pos = (WORD)((help - (LONG)magic_pack) / 2L);
  351.     /* Erster Long-Wert im Magic Pack muß 0x12123456 sein */
  352.     magic_pack[pos++] = 0x1212;
  353.     magic_pack[pos++] = 0x3456;
  354.     /* Im zweiten Long-Wert muß die Anfangsadresse des Packs stehen */
  355.     magic_pack[pos++] = (WORD)(help >> 16);
  356.     magic_pack[pos++] = (WORD)(help & 65535L);
  357.     /* Assembler-Routine kopieren */
  358.     for (i = 0; mpack[i] != (WORD)0xabcd; i++)
  359.         magic_pack[pos + i] = mpack[i];
  360.     /* 16-Bit-Prüfsumme über den Magic Pack bilden */
  361.     for (j = sum = 0; j < 256; sum += magic_pack[first + j++]);
  362.     checkpos = (pos << 1) +
  363.         (WORD)((LONG)&checksum - (LONG)mpack);
  364.     /* Checksumme so ändern, daß die Prüfsumme 0x5678 ergibt (sonst */
  365.     /* wird der Magic Pack nicht ausgeführt) */
  366.     magic_pack[checkpos >> 1] += (0x5678 - sum);
  367.     /* Reset auslösen */
  368.     Supexec(reset);
  369. }
  370.  
  371. /* Einstellungen direkt übernehmen */
  372. WORD take_settings(void)
  373. {
  374.     WORD goon;
  375.     
  376.     /* Warnung ausgeben, daß beim Übernehmen die Ramkonfiguration */
  377.     /* nicht berücksichtigt wird und daher auch der PMMU-Baum nicht */
  378.     /* gesichert werden kann. Außerdem bleibt die alte Bildschirm- */
  379.     /* adresse, falls gewünscht, hier nur bis zum nächsten Auflö- */
  380.     /* sungswechsel per Desktop erhalten */
  381.     if (settings[_SCRBASE])
  382.     {
  383.         /* Alte Bildschirmadresse ist nur bei aktiven ST-Modus möglich */
  384.         if (!(Vsetmode(-1) & STMODES))
  385.         {
  386.             form_alert(1, NOSTMODE);
  387.             return(0);
  388.         }
  389.         goon = (do_dialog(WARNING3, 0, 0L)
  390.             == W3OK);
  391.     }
  392.     else
  393.     {
  394.         goon = (do_dialog(WARNING2, 0, 0L)
  395.             == W2OK);
  396.     }
  397.     /* Einstellroutine aufrufen */
  398.     if (goon)
  399.         Supexec(set);
  400.     return(goon);
  401. }
  402.  
  403. /* Einstellungen aus dem Dialog in das Feld settings übernehmen */
  404. void put_settings(void)
  405. {
  406.     WORD i;
  407.     
  408.     settings[_DATACACHE] = 0x3100 *
  409.         !(!(MAINDIAL[DCACHE].ob_state & CROSSED));
  410.     settings[_INSTCACHE] = 0x11 *
  411.         !(!(MAINDIAL[ICACHE].ob_state & CROSSED));
  412.     for (i = 0; i < 4; i++)
  413.     {
  414.         if (MAINDIAL[rbuts[i]].ob_state & SELECTED)
  415.         {
  416.             settings[_RAMCONFIG] = i;
  417.             break;
  418.         }
  419.     }
  420.     settings[_CPU8MHZ] =
  421.         !(MAINDIAL[CPU8MHZ].ob_state & CROSSED);
  422.     settings[_BLIT8MHZ] = 4 *
  423.         !(MAINDIAL[BLIT8MHZ].ob_state & CROSSED);
  424.     settings[_BUSMODE] = 32 *
  425.         !(MAINDIAL[STEBUS].ob_state & CROSSED);
  426.     settings[_SPEAKER] = 64 *
  427.         !(MAINDIAL[SPEAKER].ob_state & CROSSED);
  428.     settings[_SCRBASE] =
  429.         MAINDIAL[SCRADR].ob_state & CROSSED;
  430.     settings[_TIMERA] =
  431.         !(!(MAINDIAL[TIMERA].ob_state & CROSSED));
  432.     settings[_MFPI7] =
  433.         !(!(MAINDIAL[MFPI7].ob_state & CROSSED));
  434.     settings[_VOLUME] = (15 - volume) * 16;
  435. }
  436.  
  437. /* Lautstärke einstellen */
  438. void set_atten(WORD redraw)
  439. {
  440.     WORD x, y, w, h;
  441.     
  442.     MAINDIAL[VOLUME].ob_x = volume * char_w;
  443.     sprintf(MAINDIAL[VOLUME].ob_spec.tedinfo->te_ptext,
  444.         "%d", volume);
  445.     /* Soll der Slider neu gezeichnet werden? */
  446.     if (redraw)
  447.     {
  448.         objc_offset(MAINDIAL, SLIDER, &x, &y);
  449.         w = MAINDIAL[SLIDER].ob_width;
  450.         h = MAINDIAL[SLIDER].ob_height;
  451.         objc_draw(MAINDIAL, SLIDER, 1,
  452.                     x, y, w, h);
  453.     }
  454.     /* Wenn der "Live"-Button gewählt ist, die Lautstärke auch */
  455.     /* tatsächlich aktivieren */
  456.     if (MAINDIAL[LIVE].ob_state & CROSSED)
  457.     {
  458.         soundcmd(LTATTEN, (15 - volume) * 16);
  459.         soundcmd(RTATTEN, (15 - volume) * 16);
  460.     }
  461. }
  462.  
  463. /* Universelle Dialogverwaltungsroutine, ruft nach solange nach jedem */
  464. /* form_do action auf, bis dieses 0 zurückgibt */
  465. WORD do_dialog(OBJECT *tree, WORD sobj,
  466.     WORD (*action)(OBJECT *tree, WORD obj))
  467. {
  468.     WORD    x, y, w, h,
  469.             cont,
  470.             obj;
  471.  
  472.     wind_update(BEG_UPDATE);
  473.     wind_update(BEG_MCTRL);
  474.     /* Größe der "billigen" Checkboxen und Radiobuttons anpassen */
  475.     /* (billig deswegen, weil ohne G_USERDEF-Objekte gearbeitet */
  476.     /* wird) */
  477.     tree_walk(tree, 0, adapt_size);
  478.     /* Dialog zentrieren und zeichnen */
  479.     form_center(tree, &x, &y, &w, &h);
  480.     form_dial(FMD_START, x, y, w, h, x, y, w, h);
  481.     objc_draw(tree, ROOT, MAX_DEPTH,
  482.         x, y, w, h);
  483.     do
  484.     {
  485.         /* Dialog bearbeiten, und ggf. die übergebene Reaktionsroutine */
  486.         /* aufrufen */
  487.         obj = form_do(tree, sobj);
  488.         if (action != NULL)
  489.             cont = (*action)(tree, obj);
  490.         else
  491.             cont = 0;
  492.     } while (cont);
  493.     /* Wenn das letzte Objekt noch selektiert ist, den Status zurück- */
  494.     /* setzen */
  495.     if ((tree[obj].ob_flags & SELECTABLE) &&
  496.         (tree[obj].ob_state & SELECTED))
  497.     {
  498.         tree[obj].ob_state &= ~SELECTED;
  499.     }
  500.     /* Dialog beenden und zuletzt gewähltes Objekt zurückgeben */
  501.     form_dial(FMD_FINISH, x, y, w, h, x, y, w, h);
  502.     wind_update(END_MCTRL);
  503.     wind_update(END_UPDATE);
  504.     return(obj);
  505. }
  506.  
  507. /* Routine, die auf das Anklicken eines Objektes im Speichern-Dialog */
  508. /* reagiert. Wird von do_dialog aufgerufen */
  509. WORD handle_savedial(OBJECT *tree, WORD obj)
  510. {
  511.     /* Doppelklick-Bit entfernen */
  512.     obj &= 0x7fff;
  513.     /* Auf das Anklicken des Radiobutton-Textes reagieren */
  514.     if (tree[obj].ob_type == G_STRING)
  515.         cross(tree, obj - 1);
  516.     /* Rückgabewert 0, wenn "Speichern" oder "Abbruch" angeklickt */
  517.     /* wurde (do_dialog wird dadurch beendet) */
  518.     return(!(tree[obj].ob_flags & EXIT));
  519. }
  520.  
  521. /* Routine zum Verwalten des Hauptdialogs, wird von do_dialog aufgerufen */
  522. WORD handle_maindial(OBJECT *tree, WORD obj)
  523. {
  524.     WORD    raw,
  525.             x, y, w, h,
  526.             old_volume,
  527.             dummy,
  528.             x2, y2;
  529.     
  530.     /* Doppelklick-Bit merken und entfernen */
  531.     raw = obj;
  532.     obj &= 0x7fff;
  533.     /* Nur etwas machen, wenn angeklicktes Objekt nicht dekativiert war */
  534.     /* (form_do bzw. intern form_button hat da je nach Objekttyp so */
  535.     /* seine Probleme) */
  536.     if (!(tree[obj].ob_state & DISABLED))
  537.     {
  538.         /* Wenn es ein Radiobutton- oder Checkbox-Text war, den */
  539.         /* dazugehörigen Button bearbeiten */
  540.         if (tree[obj].ob_type == G_STRING)
  541.             cross(tree, obj - 1);
  542.         /* Checkboxen ankreuzen, wenn sie angeklickt wurden */
  543.         if (tree[obj].ob_type == (0xfe00|G_BOX))
  544.             cross(tree, obj);
  545.         /* Verschieben des Sliders, wenn das Lautstärke-Feld angeklickt */
  546.         /* wurde */
  547.         if (obj == VOLUME)
  548.         {
  549.             objc_offset(tree, VOLUME,
  550.                 &x, &y);
  551.             w = tree[SLIDER].ob_width;
  552.             h = tree[SLIDER].ob_height;
  553.             objc_offset(tree, SLIDER,
  554.                 &x2, &y2);
  555.             graf_dragbox(tree[VOLUME].ob_width,
  556.                 tree[VOLUME].ob_height,
  557.                 x, y, x2, y2, w, h,
  558.                 &x, &y);
  559.             volume = (x - x2) / char_w;
  560.             set_atten(1);
  561.         }
  562.         /* Wurde auf den Sliderhintergrund geklickt, entsprechend */
  563.         /* reagieren */
  564.         if (obj == SLIDER)
  565.         {
  566.             wind_update(BEG_MCTRL);
  567.             graf_mkstate(&x, &y, &dummy, &dummy);
  568.             objc_offset(tree, VOLUME, &x2, &y2);
  569.             do
  570.             {
  571.                 old_volume = volume;
  572.                 if (x < x2)
  573.                 {
  574.                     if (volume >= 3)
  575.                         volume -= 3;
  576.                     else
  577.                         volume = 0;
  578.                 }
  579.                 else
  580.                 {
  581.                     if (volume <= 12)
  582.                         volume += 3;
  583.                     else
  584.                         volume = 15;
  585.                 }
  586.                 if (old_volume != volume)
  587.                 {
  588.                     set_atten(1);
  589.                     evnt_timer(80, 0);
  590.                 }
  591.             } while (!(evnt_multi(MU_TIMER|MU_BUTTON, 1, 1, 0,
  592.                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 1, 0,
  593.                 &x, &y, &dummy, &dummy, &dummy, &dummy) &
  594.                 MU_BUTTON));
  595.             wind_update(END_MCTRL);
  596.         }
  597.         /* Bei den Auf- bzw. Ab-Pfeilen die Lautstärke um eins erhöhen */
  598.         /* bzw. verringern. Bei Doppelklick auf 15 bzw. 0 setzen */
  599.         if ((obj == UP) && (volume < 15))
  600.         {
  601.             if (obj != raw)
  602.                 volume = 15;
  603.             else
  604.                 volume++;
  605.             set_atten(1);
  606.             evnt_timer(80, 0);
  607.         }
  608.         if ((obj == DOWN) && volume)
  609.         {
  610.             if (obj != raw)
  611.                 volume = 0;
  612.             else
  613.                 volume--;
  614.             set_atten(1);
  615.             evnt_timer(80, 0);
  616.         }
  617.     }
  618.     /* 0 zurückgeben, wenn ein Button mit gesetzen Exit-Flag gewählt */
  619.     /* wurde (OK, Abbruch oder Speichern). do_dialog wird dadurch */
  620.     /* beendet */
  621.     return(!(tree[obj].ob_flags & EXIT));
  622. }
  623.  
  624. /* Checkboxen ankreuzen oder Radiobuttons invertieren (letzteres wird */
  625. /* dann gebraucht, wenn nur der Text des Buttons gewählt wurde) */
  626. void cross(OBJECT *tree, WORD obj)
  627. {
  628.     WORD    x, y, w, h,
  629.             draw = 1,
  630.             dummy;
  631.     
  632.     objc_offset(tree, obj, &x, &y);
  633.     w = tree[obj].ob_width;
  634.     h = tree[obj].ob_height;
  635.     /* Bei Radiobutton form_button aufrufen, sonst den Ankreuz-Status */
  636.     /* invertieren */
  637.     if (tree[obj].ob_flags & RBUTTON)
  638.     {
  639.         form_button(tree, obj, 1, &dummy);
  640.         draw = 0;
  641.     }
  642.     else
  643.         tree[obj].ob_state ^= CROSSED;
  644.     /* Ggf. Objekt neuzeichnen */
  645.     if (draw)
  646.     {
  647.         objc_draw(tree, obj, 0, x, y, w, h);
  648.         evnt_button(1, 1, 0, &dummy, &dummy,
  649.             &dummy, &dummy);
  650.     }
  651. }
  652.  
  653. /* Routine zum Durchwandern des Objektbaumes tree, ab Objekt start. */
  654. /* Bei jedem Objekt wird action aufgerufen, wenn action 0 zurückgibt, */
  655. /* wird abgebrochen */
  656. WORD tree_walk(OBJECT *tree, WORD start,
  657.     WORD (*action)(OBJECT *tree, WORD obj))
  658. {
  659.     WORD    i,
  660.             cont;
  661.     
  662.     for (i = tree[start].ob_head, cont = 1;
  663.         (i != start) && (i != -1) && cont;
  664.         i = tree[i].ob_next)
  665.     {
  666.         cont = (*action)(tree, i);
  667.         if (cont)
  668.             cont = tree_walk(tree, i, action);
  669.     }
  670.     return(cont);
  671. }
  672.  
  673. /* Routine zum Anpassen der Größen von Radiobuttons und Checkboxen, wird */
  674. /* von tree_walk aufgerufen */
  675. WORD adapt_size(OBJECT *tree, WORD obj)
  676. {
  677.     if (tree[obj].ob_type == (0xff00 | G_BOX))
  678.     {
  679.         tree[obj].ob_width--;
  680.         tree[obj].ob_height--;
  681.         tree[obj].ob_type = 0xfe00|G_BOX;
  682.     }
  683.     return(1);
  684. }
  685.  
  686. /* Universelle Fileselektor-Routine, gleiche Parameter wie bei */
  687. /* fsel_exinput. name enthält nachher allerdings den kompletten */
  688. /* Pfadnamen, nicht nur den Namen selbst, deshalb genügend Platz */
  689. /* für name reservieren. Es wird automatisch geprüft, ob fsel_exinput */
  690. /* aufgerufen werden kann. Außerdem wird eine Meldung ausgegeben, wenn */
  691. /* fsel_(ex)input einen Fehler gemeldet hat. */
  692. WORD fileselect(char *path, char *name, WORD *button, char *title)
  693. {
  694.     char    temp1[129], temp2[129];
  695.     WORD    i, fsel_ok;
  696.     
  697.     /* Prüfen, ob fsel_exinput aufgerufen werden kann, dabei wird auch */
  698.     /* der FSEL-cookie geprüft, der z.B. von SELECTRIC angelegt wird */
  699.     if (((_GemParBlk.global[0] >= 0x0140) &&
  700.         (_GemParBlk.global[0] < 0x0200)) ||
  701.         (_GemParBlk.global[0] >= 0x0300) || get_cookie('FSEL', 0L))
  702.     {
  703.         fsel_ok = fsel_exinput(path, name, button, title);
  704.     }
  705.     else
  706.         fsel_ok = fsel_input(path, name, button);
  707.     
  708.     if (fsel_ok)
  709.     {
  710.         /* Wurde OK geklickt, kompletten Zugriffspfad für name */
  711.         /* zusammensetzen */
  712.         if (*button)
  713.         {
  714.             strcpy(temp1, path);
  715.             
  716.             i = (WORD)strlen(temp1) - 1;
  717.             
  718.             while ((temp1[i] != '\\') && (i >= 0))
  719.                 temp1[i--] = 0;
  720.             
  721.             strcpy(temp2, name);
  722.             strcpy(name, temp1);
  723.             strcat(name, temp2);
  724.         }
  725.     }
  726.     else
  727.     {
  728.         form_alert(1, "[3][Fehler bei Dateiauswahl|aufgetreten!]"
  729.                     "[Abbruch]");
  730.     }
  731.     return(fsel_ok);
  732. }
  733.  
  734. /* Überprüfen, ob übergebenes File existiert (Rückgabewert 1), oder */
  735. /* nicht (Rückgabewert 0) */
  736. WORD exist(char *file)
  737. {
  738.     DTA     disk_buf;
  739.     WORD    ret;
  740.  
  741.     graf_mouse(BUSYBEE, 0L);
  742.     
  743.     Fsetdta(&disk_buf);
  744.     ret = !Fsfirst(file, 0x17);
  745.     
  746.     graf_mouse(ARROW, 0L);
  747.     
  748.     return(ret);
  749. }
  750.  
  751. /* Überprüft, ob der Cookie cookie vorhanden ist und schreibt dessen */
  752. /* Wert dann in value. Rückgabewert 0, wenn der Cookie nicht vorhanden */
  753. /* ist, sonst 1 */
  754. WORD get_cookie(ULONG cookie, ULONG *value)
  755. {
  756.     LONG    *jar,
  757.             old_stack;
  758.     
  759.     if (Super((void *)1L) == 0L)
  760.     {
  761.         old_stack = Super(0L);
  762.         jar = *((LONG **)0x5a0L);
  763.         Super((void *)old_stack);
  764.     }
  765.     else
  766.         jar = *(LONG **)0x5a0;
  767.     
  768.     if (jar == 0L)
  769.         return(0);
  770.     
  771.     while (jar[0])
  772.     {
  773.         if (jar[0] == cookie)
  774.         {
  775.             if (value != 0L)
  776.                 *value = jar[1];
  777.             
  778.             return(1);
  779.         }
  780.         
  781.         jar += 2;
  782.     }
  783.     return(0);
  784. }
  785. /* Modulende */
  786.